/**********************************************************************
 * 
 * Name: UpsertInvoiceREST
 * Object: Sales_Invoice__c, Sales_Invoice_Detail__c
 * Purpose: Upsert Invoice and Invoice detail list from NC
 * Requirement:
 * Author: kittylau (382376269@qq.com)
 * Create Date: 2017-01-13
 * Modify History: 
 * 
 * @Url: /services/apexrest/CRM/upsertInvoiceREST
 * 接收的Json数据格式:
   {
    "data":[
        {
            //主表数据
            "invoicecode":"销售发票号",
            "invoice_hid":"销售发票主表ID",
            "corpcode":"公司编码",
            "corpname":"公司名称",
            "custcode":"客户编码",
            "custname":"客户名称",
            "dbilldate":"开票日期",
            //从表数据
            "invoice_bid":"销售发票从表ID",
            "salecode":"销售订单号",
            "sale_hid":"销售订单主表ID",
            "sale_bid":"销售订单从表ID",
            "invcode":"存货编码",
            "invname":"存货名称",
            "invspec":"产品规格",
            "invtype":"产品型号",
            "jldw":"计量单位",
            "fjldw":"辅计量单位",
            "vbatchcode":"批次号",
            "nnum":"数量",
            "noriginalcurtaxprice":"原币含税单价",
            "noriginalcursummny":"原币价税合计",
            "noriginalcurprice":"原币无税单价",
            "noriginalcurmny":"原币无税金额",
            "ts":"最后更新时间",
            //v1.4版新增
            "rowno":"行号",
            "phone":"客户电话",
            "accountcode":"客户银行账号",
            "accountname":"客户银行账户",
            "taxpayercode":"客户税号",
            "ywyname":"业务员",
            "skxy":"收款协议",
            "vsalestruname":"销售组织",
            "creceiptcustomername":"收货单位",
            "ndiscountrate":"主表发票折扣",
            "allmny":"发票总金额",
            "nstrikemny":"冲减金额",
            "fcounteractflag":"对冲标记",
            "scl":"销售订单表头产品线",
            "xsqy":"销售区域",
            "isfq":"是否分期销售",
            "iszx":"是否直销",
            "pzwh":"批准文号",
            "sbndiscountrate":"整单折扣",
            "nitemdiscountrate":"单品折扣",
            "ninvoicediscountrate":"子表发票折扣",
            "ntaxrate":"税率",
            "noriginalcurtaxnetprice":"含税净价",
            "noriginalcurnetprice":"无税净价",
            "noriginalcurtaxmny":"税额",
            "noriginalcurdiscountmny":"折扣率",
            "nsubsummny":"冲减前金额",
            "kczz":"库存组织",
            "ck":"仓库",
            "ddkh":"订单客户",
            "shdw":"收货单位",
            "prodlinename":"产品线",
            "cinvbasid":"存货基本档案pk"
        },
        {...}
        ]
   }
*  返回的Json数据格式：
  {
    "result":"0 OR 1 , 1表示成功，0表示失败", 
    "result_msg":"成功为空，失败时为失败原因信息",
    "ts":"所有记录中,更新时间最近的那一条记录的更新时间"
  }
*************************************************************************/
@RestResource(urlMapping='/CRM/upsertInvoiceREST/*')
global without sharing class UpsertInvoiceREST {
    @HttpPost
    global static RestReturnMessage upsertInvoice(List<InvoiceRestArgs> data) {     
   //global static Map<String,String> upsertInvoice(List<InvoiceRestArgs> data) {
        RestReturnMessage msg = null;
        try{
            if(data.size() > 0){
                msg = doUpsertInvoice(data);
            }else{
                throw new DmlException('没有数据');
            }
        }
        catch(Exception e){
            System.debug(LoggingLevel.INFO, '*** 错误信息: ' + e.getMessage() );
            System.debug(LoggingLevel.INFO, '*** 错误跟踪: ' + e.getStackTraceString());
            msg = Utils.getRestReturnMessage(false, e.getMessage() + ' - ' + e.getStackTraceString(),new List<Map<String,String>>());
        }
        return msg;
    }

    //得到POST数据，完成Invoice数据的插入或更新
    global static RestReturnMessage doUpsertInvoice (List<InvoiceRestArgs> data) {
        RestReturnMessage message = null;
        Datetime maxTs = Datetime.valueOf(Utils.MIN_DATE_TIME);
        System.debug(LoggingLevel.INFO, '*** Invoice Data FROM NC: ' + data);

        //保存传过来的Invoice编号 :2017年 7 月 5 日 修改 :保存传过来的发票主表PK 
        Map<String,String> mapCodes = new Map<String,String>();
        //保存传过来的客户编号
        Map<String,String> mapAccount = new Map<String,String>();
        //保存传过来的产品编号
        Map<String,String> mapProduct = new Map<String,String>();
        for(InvoiceRestArgs inv : data){
            //因为销售发票是主从表结构，但是NC传过来的数据是扁平化后报表样式的(主表和从表JOIN后的数据)
           /* if(!mapCodes.containsKey(inv.invoicecode)){
                mapCodes.put(inv.invoicecode,inv.invoicecode);
            }*/
            //2017年 7 月 5 日 修改 
            if(!mapCodes.containsKey(inv.invoice_hid)){
            	mapCodes.put(inv.invoice_hid,inv.invoice_hid);
            }
            /*
            if(!mapAccount.containsKey(inv.custcode)){
                mapAccount.put(inv.custcode, inv.custcode);
            }
            */
            if(!mapProduct.containsKey(inv.cinvbasid)){
                mapProduct.put(inv.cinvbasid, inv.cinvbasid);
            }
            
            if(!mapAccount.containsKey(inv.pk_cubasdoc)){
            	mapAccount.put(inv.pk_cubasdoc,inv.pk_cubasdoc);
            }
            //如果当前记录的更新时间大于最大时间(maxTs)，则设置最大时间为当前记录时间
            Datetime dt = Utils.parseDatetime(inv.ts);
            if(dt > maxTs){
                maxTs = dt;
            }
        }
        //得到产品记录
        List<Product__c> productList = [SELECT Id,Name,NCCode__c,pk_invbasdoc__c FROM Product__c WHERE pk_invbasdoc__c IN :mapProduct.keySet()];
        mapProduct.clear();
        for(Product__c p : productList){
            mapProduct.put(p.pk_invbasdoc__c, p.Id);
        }
        //得到已存在的Invoice记录
        List<Sales_Invoice__c> invList = 
                [SELECT Id,Name,Account__c,currency__c,deptname__c,
                    corpcode__c,corpname__c,custcode__c,custname__c,invoice_hid__c,accountcode__c,
                    accountname__c,taxpayercode__c,dbilldate__c,phone__c,ndiscountrate__c,allmny__c,
                    nsubsummny__c,nstrikemny__c,fcounteractflag__c,prodlinename__c,skxy__c,
                    creceiptcustomername__c,vsalestruname__c,ywyname__c,xsqy__c,isfq__c,iszx__c,memo__c  
                FROM Sales_Invoice__c 
                WHERE invoice_hid__c IN :mapCodes.keySet()];
        
        //把已存在的Invoice保存在Map中以用来区别是新增或更新
        Map<String,Sales_Invoice__c> mapExistInvoice = new Map<String,Sales_Invoice__c>();
        for(Sales_Invoice__c inv : invList){
            mapExistInvoice.put(inv.invoice_hid__c, inv);
        }

        //得到已存在的Invoice明细数据
        List<Sales_Invoice_Detail__c> invItemList = 
                [SELECT Id,Product__c,Sales_Invoice__c,
                    ck__c,invspec__c,invtype__c,invcode__c,invname__c,nitemdiscountrate__c,ddkh__c,
                    invoice_bid__c,invoicecode__c,invoice_hid__c,fjldw__c,noriginalcurtaxnetprice__c,
                    jldw__c,kczz__c,vbatchcode__c,pzwh__c,shdw__c,nnum__c,noriginalcurtaxmny__c,
                    ntaxrate__c,noriginalcurnetprice__c,scl__c,sale_bid__c,salecode__c,sale_hid__c,
                    noriginalcurtaxprice__c,noriginalcurprice__c,noriginalcurdiscountmny__c,
                    sbndiscountrate__c,ninvoicediscountrate__c 
                FROM Sales_Invoice_Detail__c 
                WHERE invoice_hid__c IN :mapCodes.keySet()];
        Map<String,Sales_Invoice_Detail__c> mapExistInvoiceItem = new Map<String,Sales_Invoice_Detail__c>();
        for(Sales_Invoice_Detail__c item : invItemList){
            mapExistInvoiceItem.put(item.invoice_hid__c + '-' + item.invoice_bid__c, item);
        }
        System.debug(LoggingLevel.INFO, '*** Exist Invoice On CRM: ' + invList);
        System.debug(LoggingLevel.INFO, '*** Exist Invoice Detail On CRM: ' + invItemList);

        //得到NC客户编号和CRM客户Id对应关系
        //List<Account> accList = new List<Account>([SELECT Id,Name,AccountNumber,OwnerId,Owner.ManagerId,Owner.IsActive FROM Account WHERE AccountNumber IN :mapAccount.keySet()]);
        List<Account> accList = new List<Account>([SELECT Id,Name,NCICCode__c,AccountNumber,OwnerId,Owner.ManagerId,Owner.IsActive FROM Account WHERE NCICCode__c IN :mapAccount.keySet()]);
        mapAccount.clear();
        
       // Map<String,String> mapAccountOwner = new Map<String,String>();
       // Map<String,String> mapAccountManager = new Map<String,String>();
        /*
        for(Account acc : accList){
            if(!mapAccount.containsKey(acc.AccountNumber)){
                mapAccount.put(acc.AccountNumber, acc.Id);
                // 如果用户已经是无效的了，把数据的Owner设为他的上级
                if (acc.Owner.IsActive) {
                    mapAccountOwner.put(acc.AccountNumber, acc.OwnerId);
                }
                else {
                    mapAccountManager.put(acc.AccountNumber, acc.Owner.ManagerId);
                }
            }
        }
        */
        for(Account acc : accList){
            if(!mapAccount.containsKey(acc.NCICCode__c)){
                mapAccount.put(acc.NCICCode__c, acc.Id);
             
            }
        }
        //用来保存发票从表pk的记录集合
        List<Map<String ,String>>pkList = new List<Map<String,String>>();
        //用来保存或更新的发票主表的记录集合
        List<Sales_Invoice__c> saveList = new List<Sales_Invoice__c>();
        //用来保存或更新的发票从表记录集合
        List<Sales_Invoice_Detail__c> saveItemList = new List<Sales_Invoice_Detail__c>();
        //用来记录主表记录是否已在下面的for循环中已操作
        Map<String,String> hasRunCodes = new Map<String,String>();
        //新建或更新现存Sales_Invoice__c/Sales_Invoice_Detail__c记录
        for(InvoiceRestArgs inv : data){
            if(inv.invoice_hid != null){
                //如果主表记录已处理过了，则不再处理主表数据，只处理从表数据
                if(!hasRunCodes.containsKey(inv.invoice_hid)){
                    //记录本条记录的主表数据已处理过了
                    hasRunCodes.put(inv.invoice_hid, '');
                    //主表数据
                    Sales_Invoice__c invForSave = null;
                    if(mapExistInvoice.containsKey(inv.invoice_hid)){
                        invForSave = mapExistInvoice.get(inv.invoice_hid);
                    }else{
                        invForSave = new Sales_Invoice__c();
                    }
                    invForSave.currency__c = 'RMB';//币种
                    invForSave.Name = inv.invoicecode;//销售发票号
                    
                    //invForSave.Account__c = mapAccount.containsKey(inv.pk_cubasdoc)?mapAccount.get(inv.pk_cubasdoc):null;//客户Id
                   /* if (mapAccountOwner.containsKey(inv.custcode)) {
                        invForSave.OwnerId = mapAccountOwner.get(inv.custcode);//所有人Id
                    }
                    if (mapAccountManager.containsKey(inv.custcode)) {
                        invForSave.OwnerId = mapAccountManager.get(inv.custcode);//所有人Id
                    }
                    */
                    try{
                    	if(mapAccount.containsKey(inv.pk_cubasdoc) == false) {
                       		throw new DmlException('销售发票找不到客户,发票pk:'+inv.invoice_hid+'客户Pk为:' +inv.pk_cubasdoc +'没有数据');
                   		 }
                    }catch(Exception e){
          				message =  Utils.getRestReturnMessage(false, e.getMessage() + ' - ' + e.getStackTraceString(),pkList);
                        return message;
                    }
                  	 invForSave.Account__c = mapAccount.containsKey(inv.pk_cubasdoc)?mapAccount.get(inv.pk_cubasdoc):null;//客户Id

                   /* if(invForSave.Account__c == null){

                    }
                    */
                    /*if (mapAccountOwner.containsKey(inv.pk_cubasdoc)) {
                       // invForSave.OwnerId = mapAccountOwner.get(inv.pk_cubasdoc);//所有人Id
                    }
                    if (mapAccountManager.containsKey(inv.pk_cubasdoc)) {
                        //invForSave.OwnerId = mapAccountManager.get(inv.pk_cubasdoc);//所有人Id
                    }*/
                    
                    invForSave.invoice_hid__c = inv.invoice_hid;//销售发票主表ID
                    invForSave.corpcode__c = inv.corpcode;//公司编码
                    invForSave.corpname__c = inv.corpname;//公司名称
                    invForSave.custcode__c = inv.custcode;//客户编码
                    invForSave.custname__c = inv.custname;//客户名称
                    invForSave.phone__c = inv.phone;//客户电话
                    invForSave.accountcode__c = inv.accountcode;//客户银行账号
                    invForSave.accountname__c = inv.accountname;//客户银行账号
                    invForSave.taxpayercode__c = inv.taxpayercode;//客户税号
                    invForSave.fcounteractflag__c = inv.fcounteractflag=='Y'?'对冲':'正常';//对冲标记(Y/N)
                    invForSave.prodlinename__c = inv.scl;//销售订单表头产品线
                    invForSave.skxy__c = inv.skxy;//收款协议
                    invForSave.creceiptcustomername__c = inv.creceiptcustomername;//收货单位
                    invForSave.vsalestruname__c = inv.vsalestruname;//销售组织
                    invForSave.ywyname__c = inv.ywyname;//业务员
                    invForSave.xsqy__c = inv.xsqy;//销售区域
                    invForSave.isfq__c = inv.isfq=='Y'?'是':'否';//是否分期销售(Y/N)
                    invForSave.iszx__c = inv.iszx=='Y'?'是':'否';//是否直销(Y/N)
                    invForSave.memo__c = inv.memo;//备注
                    try{
                        invForSave.ndiscountrate__c =  Decimal.valueOf(inv.ndiscountrate)/100;//主表发票折扣
                    }catch(Exception e){
                        invForSave.ndiscountrate__c = null;
                    }
                    try{
                        invForSave.allmny__c =  Decimal.valueOf(inv.allmny);//发票总金额
                    }catch(Exception e){
                        invForSave.allmny__c = null;
                    }
                    try{
                        invForSave.nsubsummny__c =  Decimal.valueOf(inv.nsubsummny);//冲减前金额
                    }catch(Exception e){
                        invForSave.nsubsummny__c = null;
                    }
                    try{
                        invForSave.nstrikemny__c =  Decimal.valueOf(inv.nstrikemny);//冲减金额
                    }catch(Exception e){
                        invForSave.nstrikemny__c = null;
                    }
                    try{
                        invForSave.dbilldate__c = Date.valueOf(inv.dbilldate);//开票日期
                    }catch(Exception e){
                        invForSave.dbilldate__c = null;
                    }
                    saveList.add(invForSave);
                }

                //从表数据
                Sales_Invoice_Detail__c invItem = null;
                if(mapExistInvoiceItem.containsKey(inv.invoice_hid + '-' + inv.invoice_bid)){
                    invItem = mapExistInvoiceItem.get(inv.invoice_hid + '-' + inv.invoice_bid);
                }else{
                    invItem = new Sales_Invoice_Detail__c();
                }
                invItem.invoicecode__c = inv.invoicecode;//销售发票号
                invItem.invoice_hid__c = inv.invoice_hid;//销售发票主表ID
                invItem.invoice_bid__c = inv.invoice_bid;//销售发票从表ID
                invItem.salecode__c = inv.salecode;//销售订单号
                invItem.sale_hid__c = inv.sale_hid;//销售订单主表ID
                invItem.sale_bid__c = inv.sale_bid;//销售订单从表ID
                invItem.invcode__c = inv.invcode;//存货编码
                invItem.invname__c = inv.invname;//存货名称
                invItem.invspec__c = inv.invspec;//产品规格
                invItem.invtype__c = inv.invtype;//产品型号
                invItem.jldw__c = inv.jldw;//计量单位
                invItem.fjldw__c = inv.fjldw;//辅计量单位
                invItem.vbatchcode__c = inv.vbatchcode;//批次号
                invItem.scl__c = inv.prodlinename;//产品线
                invItem.pzwh__c = inv.pzwh;//批准文号
                invItem.kczz__c = inv.kczz;//库存组织
                invItem.ck__c = inv.ck;//仓库
                invItem.ddkh__c = inv.ddkh;//订单客户
                invItem.shdw__c = inv.shdw;//收货单位
                invItem.dr__c = inv.dr=='1'?true:false;//删除标记
                try{
                    invItem.sbndiscountrate__c = Decimal.valueOf(inv.sbndiscountrate)/100;//整单折扣
                }catch(Exception e){
                    invItem.sbndiscountrate__c = null;
                }
                try{
                    invItem.nitemdiscountrate__c = Decimal.valueOf(inv.nitemdiscountrate)/100;//单品折扣
                }catch(Exception e){
                    invItem.nitemdiscountrate__c = null;
                }
                try{
                    invItem.ninvoicediscountrate__c = Decimal.valueOf(inv.ninvoicediscountrate)/100;//子表发票折扣
                }catch(Exception e){
                    invItem.ninvoicediscountrate__c = null;
                }
                try{
                    invItem.ntaxrate__c = Decimal.valueOf(inv.ntaxrate)/100;//税率
                }catch(Exception e){
                    invItem.ntaxrate__c = null;
                }
                try{
                    invItem.noriginalcurtaxnetprice__c = Decimal.valueOf(inv.noriginalcurtaxnetprice);//含税净价
                }catch(Exception e){
                    invItem.noriginalcurtaxnetprice__c = null;
                }
                try{
                    invItem.noriginalcurnetprice__c = Decimal.valueOf(inv.noriginalcurnetprice);//无税净价
                }catch(Exception e){
                    invItem.noriginalcurnetprice__c = null;
                } 
                try{
                    invItem.noriginalcurtaxmny__c = Decimal.valueOf(inv.noriginalcurtaxmny);//税额
                }catch(Exception e){
                    invItem.noriginalcurtaxmny__c = 0;
                } 
                try{
                    invItem.noriginalcurdiscountmny__c = Decimal.valueOf(inv.noriginalcurdiscountmny)/100;//折扣率
                }catch(Exception e){
                    invItem.noriginalcurdiscountmny__c = null;
                } 
                invItem.Product__c = mapProduct.containsKey(inv.cinvbasid)?mapProduct.get(inv.cinvbasid):null;//产品
                try{
                    invItem.nnum__c = Decimal.valueOf(inv.nnum);//数量
                }catch(Exception e){
                    invItem.nnum__c = 0;
                }
                try{
                    invItem.noriginalcurtaxprice__c = Decimal.valueOf(inv.noriginalcurtaxprice);//原币含税单价
                }catch(Exception e){
                    invItem.noriginalcurtaxprice__c = null;
                }
                try{
                    invItem.noriginalcurprice__c = Decimal.valueOf(inv.noriginalcurprice);//原币无税单价
                }catch(Exception e){
                    invItem.noriginalcurprice__c = null;
                }
                saveItemList.add(invItem);
                
                //
                Map<String ,String> pk = new Map<String ,String>();
                pk.put('mainpk',inv.invoice_hid);
                pk.put('sonpk',inv.invoice_bid);                
                pkList.add(pk);
            }
        }
        ///设置事务还原点，当操作失败时用来回滚
        SavePoint sp = Database.setSavePoint();
        try{
            //保存主表数据
            Upsert saveList invoice_hid__c ;
            //取得保存后的发票Id和NC销售发票号的对应关系
            mapCodes.clear();
            for(Sales_Invoice__c inv : saveList){
                if(!mapCodes.containsKey(inv.invoice_hid__c)){
                    mapCodes.put(inv.invoice_hid__c, inv.Id);
                }
            }
            //设置从表的Sales_Invoice__c
            for(Sales_Invoice_Detail__c dInv : saveItemList){
                dInv.Sales_Invoice__c = mapCodes.containsKey(dInv.invoice_hid__c)?mapCodes.get(dInv.invoice_hid__c):null;
            }
            //保存从表数据
            Upsert saveItemList invoice_bid__c;
          
            message = Utils.getRestReturnMessage(true,'',pkList);
			 //System.debug('ddddddd' + pkList);
			 //System.debug('ddddddd' + Message);

            //message = Utils.getRestReturnMessage(true,'成功导入记录条数['+ saveItemList.size() +']',maxTs);
        }
        catch(Exception e) {
            System.debug(LoggingLevel.INFO, '*** 错误信息: ' + e.getMessage() );
            System.debug(LoggingLevel.INFO, '*** 错误跟踪: ' + e.getStackTraceString());
            //保存数据失败，回滚事务
            Database.rollback(sp);
            message =  Utils.getRestReturnMessage(false, e.getMessage() + ' - ' + e.getStackTraceString(),pkList);
            
            //message =  Utils.getRestReturnMessage(false, e.getMessage() + ' - ' + e.getStackTraceString(),Datetime.valueOf(Utils.MIN_DATE_TIME));
        }
        
        return message; 
    }
	
    //根据NC提供的JSON结构来确定的Invoice字段集合
    global class InvoiceRestArgs {
        //主表数据
        global String invoicecode;//销售发票号
        global String dbilldate;//开票日期
        global String invoice_hid;//销售发票主表ID
        global String corpcode;//公司编码
        global String corpname;//公司名称
        global String custcode;//客户编码
        global String custname;//客户名称
        //从表数据
        global String invoice_bid;//销售发票从表ID
        global String salecode;//销售订单号
        global String sale_hid;//销售订单主表ID
        global String sale_bid;//销售订单从表ID
        global String invcode;//存货编码
        global String invname;//存货名称
        global String invspec;//产品规格
        global String invtype;//产品型号
        global String jldw;//计量单位
        global String fjldw;//辅计量单位
        global String vbatchcode;//批次号
        global String nnum;//数量
        global String noriginalcurtaxprice;//原币含税单价
        global String noriginalcursummny;//原币价税合计
        global String noriginalcurprice;//原币无税单价
        global String noriginalcurmny;//原币无税金额
        global String ts;//最后更新时间
        //v1.4版新增主表
        global String rowno;//行号
        global String phone;//客户电话
        global String accountcode;//客户银行账号
        global String accountname;//客户银行账号
        global String taxpayercode;//客户税号
        global String ndiscountrate;//主表发票折扣
        global String allmny;//发票总金额
        global String nsubsummny;//冲减前金额
        global String nstrikemny;//冲减金额
        global String fcounteractflag;//对冲标记(Y/N)
        global String scl;//表头产品线
        global String skxy;//收款协议
        global String creceiptcustomername;//收货单位
        global String vsalestruname;//销售组织
        global String ywyname;//业务员
        global String xsqy;//销售区域
        global String isfq;//是否分期销售
        global String iszx;//是否直销(Y/N)
        global String memo;//备注
        //v1.4版新增从表
        global String prodlinename;//产品线
        global String pzwh;//批准文号
        global String sbndiscountrate;//整单折扣
        global String nitemdiscountrate;//单品折扣
        global String ninvoicediscountrate;//子表发票折扣
        global String ntaxrate;//税率
        global String noriginalcurtaxnetprice;//含税净价
        global String noriginalcurnetprice;//无税净价
        global String noriginalcurtaxmny;//税额
        global String noriginalcurdiscountmny;//折扣率
        global String kczz;//库存组织
        global String ck;//仓库
        global String ddkh;//订单客户
        global String shdw;//收货单位
        //v1.5新增从表 nc那边传过来的数据里面多了一个dr字段，1或者0
        global String dr;
        global String cinvbasid;
        //新增字段
        global String pk_cubasdoc;   //--开票单位客户档案pk
    }
}